/**
 Emma_project
 Copyright (C) 2015  Rodrigo Garcia

 This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "UserSerialInterface.h"

void SerialUserInterface(void)
{
  user_serial_interface_state = MAIN_MENU;
  unsigned char o = 'a';
  while(o!='g' && !(PINC &(1<<2))) // testing usart comunication
    {
      o = usart_rx_1s();
      printf("%c < press g\n",o);
    }
  ClearSerialScreen();
  UpdateFlagsFromEEPROM();

  unsigned char ns_T = Nelements_STR_SensorsNamesTemperature1();
  unsigned char ns_RH = Nelements_STR_SensorsNamesRelativeHumidity();
  unsigned char total_sensors = ns_T + ns_RH;

  unsigned char s_index = 0;

  // checks if still in config mode
  while(!(PINC & (1<<2))) 
    {
      char str_buff[30];

      if(user_serial_interface_state==MAIN_MENU) // -- main menu
	{
	  printf("-*EMMA*-\n");
	  Copy_STR_User_Serial_Interface(str_buff, 0);
	  printf("\n1. %s", str_buff); // add/remove sensor

	  Copy_STR_User_Serial_Interface(str_buff, 1);
	  printf("\n2. %s", str_buff); // clock

	  Copy_STR_User_Serial_Interface(str_buff, 2);
	  printf("\n3. %s", str_buff); // Log interval

	  o = usart_rx_1s();

	  ClearSerialScreen();
	  if(o=='1')
	    user_serial_interface_state = ADD_REMOVE_SENSOR;
	  else if(o=='2')
	    user_serial_interface_state = CLOCK;
	  else if(o=='3')
	    user_serial_interface_state = TIME_INTERVAL;
	}
      else if(user_serial_interface_state==ADD_REMOVE_SENSOR) // -- add or remove sensor
	{
	  ShowAddRemoveSensorMenu(s_index);

	  o = usart_rx(); // ask for user input (infinite loop)

	  if(o == 'n' && (s_index < total_sensors)) // next
	    s_index++;
	  else if(o == 'p' && (s_index>0)) // prev
	    s_index--;
	  else if(o == 'a') // add/remove sensor (Toggles enabling and disabling a sensor)
	    {
	      if(s_index < ns_T) // temperature
		{
		  if(CheckIfSensorIsEnabled(s_index, temperature_ctrl))
		    ClearEEPROMFlag(TEMPERATURE_CTRL_BYTE1, s_index);
		  else
		    SetEEPROMFlag(TEMPERATURE_CTRL_BYTE1, s_index);
		}
	      else if(s_index < (ns_T+ns_RH)) // realtive humidity
		{
		  if(CheckIfSensorIsEnabled(s_index-(ns_T), relative_humidity_ctrl))
		    ClearEEPROMFlag(RELATIVE_HUMIDITY_CTRL_BYTE1, s_index-(ns_T));
		  else
		    SetEEPROMFlag(RELATIVE_HUMIDITY_CTRL_BYTE1, s_index-(ns_T));
		}
	      // more physical phenomenon
	      // ..
	      change_table_header = 1; // to update table_header
	      UpdateFlagsFromEEPROM();
	    }
	  else if(o == 'q')
	    {
	      user_serial_interface_state = MAIN_MENU;
	      s_index = 0;
	    }
	     
	}
      else if(user_serial_interface_state==CLOCK) // set clock
	{
	  char time[] = "000000000000";
	  // set hour
	  char i;
	  for(i=0; i<12; i++)
	    {
	      ShowClockmenu(i);
	      ShowTime(time);
	      time[i] = usart_rx(); // wait for user input
	    }
	  ShowTime(time);

	  /* printf("== %d %d %d %d %d %d %d %d %d %d %d", */
	  /* 	 time[0],time[1],time[2],time[3],time[4],time[5],time[6],time[7],time[8],time[10],time[11]); */
	  /* _delay_ms(2800); */
	  /* printf("--%d--", ValidateTime(time)); */
	  /* _delay_ms(2800); */

	  if(ValidateTime(time)) // writes time into RTC
	    { 
	      struct RTC_time rtc_time;
	      rtc_time.hour = (time[0]-0x30)*10 + (time[1]-0x30);
	      rtc_time.min = ((time[2]-0x30)*10 + (time[3]-0x30));
	      rtc_time.sec = ((time[4]-0x30)*10 + (time[5]-0x30));
	      rtc_time.mday = ((time[6]-0x30)*10 + (time[7]-0x30));
	      rtc_time.mon = ((time[8]-0x30)*10 + (time[9]-0x30));
	      rtc_time.year = ((time[10]-0x30)*10 + (time[11]-0x30));
	      
	      if(!DS3231_set_time(rtc_time)) // no errors writing RTC
		{
		  Copy_STR_User_Serial_Interface(str_buff, 5);
		  printf("%s\n", str_buff);
		  ShowClock();
		}
	    }
	  else
	      printf("Err!");
	  _delay_ms(3000);

	  user_serial_interface_state = MAIN_MENU;
	  /*
	    hh:mm:ss DD-MM-YY
	    Reloj: 
	    > Hora hh:mm:ss
	      Fecha DD-MM-YY
	    - - - -
	    Reloj ajustado a:
	    hh:mm:ss  DD-MM-YY
	   */
	}
      else if(user_serial_interface_state==TIME_INTERVAL) // set time interval
	{
	  /*
	    hh:mm:ss
	    Ajustar a:
	    > hh:mm:ss = 00:00:00
	   - - - -
	   ajustado a:
	   hh:mm:ss
	   */
	  unsigned char ti[7]={0x2d,0x2d,0x2d,0x2d,0x2D,0x2D,0x00}; // - - - - - - - 
	  unsigned char aux;
	  /* unsigned char c_hour = (unsigned char)(interval_time_sum>>16); */
	  /* unsigned char c_min = (unsigned char)((interval_time_sum>>8)&0xFF); */
	  /* unsigned char c_sec = (unsigned char)(interval_time_sum&0xFF); */
	  unsigned char c_hour = (unsigned char)(interval_time_sum/3600);
	  unsigned char c_min = (unsigned char)(((interval_time_sum)/60)%60);
	  unsigned char c_sec = (unsigned char)(interval_time_sum%60);
	  unsigned char i;
	  for(i=0; i<6; i++)
	    {
	      ClearSerialScreen();
	      // Show Current Time interval
	      Copy_STR_User_Serial_Interface(str_buff, 5);
	      printf("%s %02d:%02d:%02d",str_buff, c_hour, c_min, c_sec);
	      printf("\n> hh:mm:ss =");
	      // Show Time interval being set
	      printf(" %c%c:%c%c:%c%c",ti[0],ti[1],ti[2],ti[3],ti[4],ti[5]);
	      // process inserted interval
	      aux = usart_rx();
	      // control input
	      if(i==0 && (aux>0x32 || aux<0x30)) // 0-2
		break;
	      if(i==1 && (aux>0x34 || aux<0x30)) // 0-4
		break;
	      if((i==2||i==4) && (aux>0x35 || aux<0x30)) // 0-5
		break;
	      if((i==3||i==5) && (aux>0x39 || aux<0x30)) // 0-9
		break;

	      ti[i] = aux;
	    }
	  if(i == 6) // valid interval
	    {
	      SetTimeInterval((ti[0]-0x30)*10 + (ti[1]-0x30) , 
			      (ti[2]-0x30)*10 + (ti[3]-0x30) ,
			      (ti[4]-0x30)*10 + (ti[5]-0x30));

	      change_table_header = 1; // to update table_header

	      //show success
	      //	      ClearSerialScreen();
	      Copy_STR_User_Serial_Interface(str_buff , 2);
	      printf("%s ",str_buff);
	      Copy_STR_User_Serial_Interface(str_buff, 5);
	      printf("%s\n%c%c:%c%c:%c%c",str_buff,
		     ti[0],ti[1],ti[2],ti[3],ti[4],ti[5]);
	    }
	  else
	    printf("\nErr!");

	  _delay_ms(3000);
	  user_serial_interface_state = MAIN_MENU;
	}
    }
      
}

void ShowAddRemoveSensorMenu(unsigned char s_index)
{ // add/remove sensor menu
  //  unsigned char number_of_sensors = Nelements_STR_SensorsNamesTemperature1() + Nelements_STR_SensorsNamesRelativeHumidity();

  unsigned char o=' ';

  // === Show up to 3 sensors ===
  /*
    >   DHT11
      * LM35
        HS11
    n= v  p= ^  a= *  q= salir
    - - - -
    Save?
    y/n
    - - - -
   */
  unsigned char str_buff[20];
  unsigned char ns_RH = Nelements_STR_SensorsNamesRelativeHumidity();
  unsigned char ns_T = Nelements_STR_SensorsNamesTemperature1();

  ClearSerialScreen();
  printf("%d\n",s_index);
  printf(">");
  // see if the sensor is marked
  unsigned char i;
  for(i=s_index; i<(s_index+3); i++)
    {
      if(i < ns_T) 
	{// temperature
	  Copy_STR_SensorsNamesTemperature1(str_buff, i);
	  printf(" ");

	  if(CheckIfSensorIsEnabled(i, temperature_ctrl))
	    printf("*"); // * indicates that the sensor is enabled
	  else
	    printf(" "); // `space` sensor is not enabled

	  printf(" %s",str_buff); // sensor's name
	}
      else if(i < (ns_T + ns_RH))
	{ // realtive humidity
	  Copy_STR_SensorsNamesRelativeHumidity(str_buff, i-(ns_T));
	  printf(" ");
	  
	  if(CheckIfSensorIsEnabled(i-ns_T, relative_humidity_ctrl))
	    printf("*"); 
	  else
	    printf(" "); 

	  printf(" %s",str_buff); // sensor's name
	}
      //.. other physical phenomenom
      printf("\n\r ");
    }
  // ==
  printf("n= v   p= ^   a= *   q= <");
}

char CheckIfSensorIsEnabled(unsigned char s_index, unsigned char eeprom_byte)
{
  if(eeprom_byte & (1<<s_index)) // sensor enabled
    return 1;
  return 0;
}

void ClearSerialScreen(void)
{
  unsigned char i;
  for(i=25; i>0; i--)
    printf("\n");
  printf("\r");
}

void ShowClockmenu(char i)
{
  char str_buff[20];
  ClearSerialScreen();
  ShowClock();
  Copy_STR_User_Serial_Interface(str_buff, 1);
  printf("\n%s\n", str_buff);

  Copy_STR_User_Serial_Interface(str_buff, 3); // hour
  //printf("%s hh:mm:ss", str_buff);

  if(i<6)
    printf(">");
  else
    printf(" ");

  printf(" %s hh:mm:ss\n", str_buff);

  if(i>=6)
    printf(">");
  else
    printf(" ");
  Copy_STR_User_Serial_Interface(str_buff, 4); // date
  printf(" %s DD-MM-YY\n ", str_buff);
}

void ShowTime(const char *time)
{
  printf("%c%c:%c%c:%c%c\n",time[0], time[1], time[2], time[3],
	 time[4], time[5]);
  printf(" %c%c-%c%c-%c%c\n",time[6], time[7], time[8], time[9], time[10],
	 time[11]);
}

void ShowClock(void)
{
  struct RTC_time rtcTime;
  DS3231_get_time(&rtcTime);
  printf("%02u:%02u:%02u %02u-%02u-%02u", rtcTime.hour,rtcTime.min,
	 rtcTime.sec,rtcTime.mday, rtcTime.mon, rtcTime.year);
}

char ValidateTime(const char *time)
{
  char i;
  for(i=0; i<12; i++)
    {
      if((time[(unsigned char)i]<0x30) || (time[(unsigned char)i]>0x39)) // not valid character
	return 0;
    }
  return 1; // number charcter
}

